{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "GREMLIN_TF_simple.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/sokrypton/GREMLIN_CPP/blob/master/GREMLIN_TF_simple.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3SHD25hwV_FA",
        "colab_type": "text"
      },
      "source": [
        "## GREMLIN_TF_simple\n",
        "This is a bare minimum version of GREMLIN re-written to work with keras + tensorflow (v1 and v2).\n",
        "\n",
        "For the old version of GREMLIN_TF_simple, that currently only works w/ tensorflow v1 [see here](https://colab.research.google.com/github/sokrypton/GREMLIN_CPP/blob/master/GREMLIN_TF1_simple.ipynb)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "dyhXMSv5HbpK",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# ------------------------------------------------------------\n",
        "# \"THE BEERWARE LICENSE\" (Revision 42):\n",
        "# <so@g.harvard.edu> and <koo@cshl.edu> wrote this code.\n",
        "# As long as you retain this notice, you can do whatever you want\n",
        "# with this stuff. If we meet someday, and you think this stuff\n",
        "# is worth it, you can buy us a beer in return.\n",
        "# --Sergey Ovchinnikov and Peter Koo\n",
        "# ------------------------------------------------------------"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PB3ZQBCcSh-A",
        "colab_type": "text"
      },
      "source": [
        "Select tensorflow version for Google Colab"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "-4AYW-IWRflV",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "3a411cb3-60f0-4c4c-aab1-427fd53bc848"
      },
      "source": [
        "%tensorflow_version 2.x"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "TensorFlow 2.x selected.\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZdGBxCYlURSw",
        "colab_type": "text"
      },
      "source": [
        "## Load some libraries"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "aJcHKRLQQAS4",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import numpy as np\n",
        "import matplotlib.pylab as plt\n",
        "import string"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ijbQXxzlYKAk",
        "colab_type": "text"
      },
      "source": [
        "## Convert FASTA to MSA np.array()"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "wU8Gzh1FQEZl",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Update 17Oct2019: 2X faster version of mk_msa() contributed by Ivan Anishchenko\n",
        "\n",
        "def parse_fasta(filename, a3m=False):\n",
        "  '''function to parse fasta file'''\n",
        "  \n",
        "  if a3m:\n",
        "    # for a3m files the lowercase letters are removed\n",
        "    # as these do not align to the query sequence\n",
        "    rm_lc = str.maketrans(dict.fromkeys(string.ascii_lowercase))\n",
        "    \n",
        "  header, sequence = [],[]\n",
        "  lines = open(filename, \"r\")\n",
        "  for line in lines:\n",
        "    line = line.rstrip()\n",
        "    if line[0] == \">\":\n",
        "      header.append(line[1:])\n",
        "      sequence.append([])\n",
        "    else:\n",
        "      if a3m: line = line.translate(rm_lc)\n",
        "      else: line = line.upper()\n",
        "      sequence[-1].append(line)\n",
        "  lines.close()\n",
        "  sequence = [''.join(seq) for seq in sequence]\n",
        "  return header, sequence\n",
        "  \n",
        "def mk_msa(seqs):\n",
        "  '''one hot encode msa'''\n",
        "  alphabet = list(\"ARNDCQEGHILKMFPSTWYV-\")\n",
        "  states = len(alphabet)\n",
        "  \n",
        "  alpha = np.array(alphabet, dtype='|S1').view(np.uint8)\n",
        "  msa = np.array([list(s) for s in seqs], dtype='|S1').view(np.uint8)  \n",
        "  for n in range(states):\n",
        "    msa[msa == alpha[n]] = n  \n",
        "  msa[msa > states] = states-1\n",
        "  \n",
        "  return np.eye(states)[msa]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "z8j_kpFSUeFT",
        "colab_type": "text"
      },
      "source": [
        "## load example"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Nn5oow4zP9ht",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!wget -q -nc https://gremlin2.bakerlab.org/db/PDB_EXP/fasta/4FAZA.fas"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ipoWnWOCQryY",
        "colab_type": "code",
        "outputId": "83a20ff0-f61d-490d-8af9-78b21af69e8b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "names, seqs = parse_fasta(\"4FAZA.fas\")\n",
        "msa = mk_msa(seqs)\n",
        "\n",
        "print(msa.shape)"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "(817, 62, 21)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ue1PNibZ0bYY",
        "colab_type": "text"
      },
      "source": [
        "### compute weight for each sequence\n",
        "if your alignment has many redundant sequences, these should be downweighted!\n",
        "For example, if two sequences share more 80% identity, they are effectively one sequence, and thus each would get a weight of 0.5."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ug0PcWP1J_EA",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from scipy.spatial.distance import pdist, squareform\n",
        "def get_eff(msa, eff_cutoff=0.8):\n",
        "  if msa.ndim == 3: msa = msa.argmax(-1)    \n",
        "  # pairwise identity  \n",
        "  msa_sm = 1.0 - squareform(pdist(msa,\"hamming\"))\n",
        "  # weight for each sequence\n",
        "  msa_w = (msa_sm >= eff_cutoff).astype(np.float)\n",
        "  msa_w = 1/np.sum(msa_w,-1)\n",
        "  \n",
        "  return msa_w"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Z5tO8gu2Plln",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "msa_weights = get_eff(msa)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "eNAbmgeOQ1UK",
        "colab_type": "text"
      },
      "source": [
        "## GREMLIN\n",
        "GREMLIN is technically an \"autoencoder\" with a single dense (or fully-connected) layer between the input and output.\n",
        "GREMLIN minimizes the difference between the input and output. The \"latent\" variables are the (w)eights/(b)ias of the dense layer.\n",
        "\n",
        "* loss = categorical_crossentropy(msa,  softmax(dot(msa, w) + b))\n",
        " - the math is identical to computing the \"pseudolikelihood\" as in GREMLIN()\n",
        " \n",
        "* msa\n",
        " - msa.shape = (batch, L x 21)\n",
        " - 21 =  (20 amino acids + 1 gap) categories\n",
        "* w = weight\n",
        " - w.shape = (L x 21, L x 21)\n",
        " -  aka two-body term of the MRF (aka co-evolution)\n",
        " -  note: the w matrix is symmetrized and the diagional is set to zero\n",
        "* b = bias \n",
        " - b.shape = (L x 21)\n",
        " - aka one-body-term of the MRF (aka conservation)"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "pvS4lzAmZL-3",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import tensorflow as tf\n",
        "import tensorflow.keras.backend as K\n",
        "\n",
        "from tensorflow.keras.models import Sequential\n",
        "from tensorflow.keras.layers import Dense, Flatten, Reshape, Activation\n",
        "from tensorflow.keras.optimizers import Adam\n",
        "from tensorflow.keras.regularizers import l2\n",
        "from tensorflow.keras.initializers import Zeros, Constant\n",
        "from tensorflow.keras.losses import categorical_crossentropy"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bYFxhwGoQxyT",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def GREMLIN_simple(msa, msa_weights=None, lam=0.01, \n",
        "                   opt=None, opt_rate=None,\n",
        "                   opt_batch=None, opt_epochs=100):\n",
        "  '''\n",
        "  ------------------------------------------------------\n",
        "  inputs\n",
        "  ------------------------------------------------------\n",
        "   msa         : msa input       shape=(N,L,A)\n",
        "   msa_weights : weight per seq  shape=(N,)\n",
        "  ------------------------------------------------------\n",
        "  optional inputs\n",
        "  ------------------------------------------------------\n",
        "   lam         : L2 regularization weight\n",
        "   opt         : optimizer\n",
        "   opt_rate    : learning rate\n",
        "   opt_batch   : batch size\n",
        "   opt_epochs  : number of epochs\n",
        "  ------------------------------------------------------\n",
        "  outputs \n",
        "  ------------------------------------------------------\n",
        "   v           : conservation    shape=(L,A)\n",
        "   w           : coevolution     shape=(L,A,L,A)\n",
        "  ------------------------------------------------------\n",
        "  '''\n",
        "  \n",
        "  # [N]umber of sequences, [L]ength, and size of [A]lphabet\n",
        "  N,L,A = msa.shape\n",
        "    \n",
        "  # reset any open sessions/graphs\n",
        "  K.clear_session()\n",
        "  \n",
        "  #############################\n",
        "  # the model\n",
        "  #############################  \n",
        "  \n",
        "  # constraints\n",
        "  def cst_w(x):\n",
        "    '''symmetrize, set diagonal to zero'''\n",
        "    x = (x + K.transpose(x))/2    \n",
        "    zero_mask = K.constant((1-np.eye(L))[:,None,:,None],dtype=tf.float32)\n",
        "    x = K.reshape(x,(L,A,L,A)) * zero_mask\n",
        "    return K.reshape(x,(L*A,L*A))\n",
        "  \n",
        "  # initialiation\n",
        "  if msa_weights is None:\n",
        "    Neff = N\n",
        "    pssm = msa.sum(0)\n",
        "  else:\n",
        "    Neff = msa_weights.sum()\n",
        "    pssm = (msa.T*msa_weights).sum(-1).T\n",
        "  \n",
        "  ini_v = np.log(pssm + lam * np.log(Neff))\n",
        "  ini_v = Constant(ini_v - ini_v.mean(-1,keepdims=True))\n",
        "  ini_w = Zeros\n",
        "  \n",
        "  # regularization\n",
        "  lam_v = l2(lam/N)\n",
        "  lam_w = l2(lam/N * (L-1)*(A-1)/2)\n",
        "  \n",
        "  # model\n",
        "  model = Sequential()\n",
        "  model.add(Flatten(input_shape=(L,A)))\n",
        "  model.add(Dense(units=L*A,\n",
        "                  kernel_initializer=ini_w,\n",
        "                  kernel_regularizer=lam_w,\n",
        "                  kernel_constraint=cst_w,\n",
        "                  bias_initializer=ini_v,\n",
        "                  bias_regularizer=lam_v)) \n",
        "  model.add(Reshape((L,A)))\n",
        "  model.add(Activation(\"softmax\"))\n",
        "  \n",
        "  #############################\n",
        "  # compile model\n",
        "  #############################\n",
        "  # loss function = CCE = -Pseudolikelihood\n",
        "  @tf.function\n",
        "  def CCE(true,pred):\n",
        "    return K.sum(-true * K.log(pred + 1e-8),axis=(1,2))\n",
        "  \n",
        "  # optimizer settings\n",
        "  if opt is None: opt = Adam\n",
        "  if opt_rate is None: opt_rate = 0.1 * np.log(Neff)/L\n",
        "  if opt_batch is None: opt_batch = N\n",
        "\n",
        "  model.compile(opt(opt_rate),CCE)  \n",
        "    \n",
        "  #############################\n",
        "  # fit model\n",
        "  #############################\n",
        "  model.fit(msa, msa, sample_weight=msa_weights,\n",
        "            batch_size=opt_batch, epochs=opt_epochs,\n",
        "            verbose=False)\n",
        "\n",
        "  # report loss\n",
        "  loss = model.evaluate(msa, msa, sample_weight=msa_weights, verbose=False) * N\n",
        "  print(f\"loss: {loss}\")\n",
        "  \n",
        "  #############################\n",
        "  # return weights\n",
        "  #############################\n",
        "  w,v = model.get_weights()\n",
        "  return v.reshape((L,A)), w.reshape((L,A,L,A))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "BEnCFJg1XBaf",
        "colab_type": "code",
        "outputId": "acb4dde7-7425-4080-a9ed-02a6eb89f5f2",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 68
        }
      },
      "source": [
        "%%time\n",
        "V, W = GREMLIN_simple(msa, msa_weights)"
      ],
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "loss: 26911.78012466431\n",
            "CPU times: user 2.68 s, sys: 283 ms, total: 2.96 s\n",
            "Wall time: 3.3 s\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2VYRfajHSgv1",
        "colab_type": "text"
      },
      "source": [
        "## get contacts"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "mTw-NPuCSESQ",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def get_mtx(W):\n",
        "  '''\n",
        "  ------------------------------------------------------\n",
        "  inputs\n",
        "  ------------------------------------------------------\n",
        "   w           : coevolution   shape=(L,A,L,A)\n",
        "  ------------------------------------------------------\n",
        "  outputs \n",
        "  ------------------------------------------------------\n",
        "   raw         : l2norm(w)     shape=(L,L)\n",
        "   apc         : apc(raw)      shape=(L,L)\n",
        "  ------------------------------------------------------\n",
        "  '''\n",
        "  # l2norm of 20x20 matrices (note: we ignore gaps)\n",
        "  raw = np.sqrt(np.sum(np.square(W[:,:-1,:,:-1]),(1,3)))\n",
        "\n",
        "  # apc (average product correction)\n",
        "  ap = np.sum(raw,0,keepdims=True)*np.sum(raw,1,keepdims=True)/np.sum(raw)\n",
        "  apc = raw - ap\n",
        "  np.fill_diagonal(apc,0)\n",
        "  \n",
        "  return raw, apc"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hjJrppRvS2pV",
        "colab_type": "code",
        "outputId": "396fc181-839f-45dc-bcd2-76e7f781cf62",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 318
        }
      },
      "source": [
        "raw, apc = get_mtx(W)\n",
        "\n",
        "plt.figure(figsize=(10,5))\n",
        "plt.subplot(1,2,1); plt.imshow(raw, cmap='Blues'); plt.title(\"raw\")\n",
        "plt.subplot(1,2,2); plt.imshow(apc, cmap='Blues'); plt.title(\"apc\")\n",
        "plt.show()"
      ],
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlAAAAEtCAYAAADHtl7HAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0\ndHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nOy9d5hdV3m3/SxJ03svmtGMuqxeLXeD\nWwICm2LTHYNNMQESrnzvFyCUEMrLS0kgeUMgEAjNxuDgYGIMGAzuxkWyuiWra0aj6b1qyn7/kGzN\n797HMzq2NC4893Vx4aVT9t5rr73OnrPu83tCFEXmOI7jOI7jnDrTXugdcBzHcRzHeanhN1CO4ziO\n4zhJ4jdQjuM4juM4SeI3UI7jOI7jOEniN1CO4ziO4zhJ4jdQjuM4juM4SeI3UI7jOI7jOEniN1CO\n4ziO4zhJ4jdQzmkjhDDjhd4Hx3Ecx5kK/AbKeV6EEA6GED4SQthqZn0hhE+EEPaFEHpCCDtDCK8f\n99xDIYQ1J/777SGEKISw5ET7hhDCz1+gw3Ac50+UEMJHE81ZIYR3hhAeDCH8awihK4SwK4Rw6bjX\nFYYQ/jOE0BBC6PD5608Pv4FyTgdvNbMNZpZvZrvN7EIzyzOzfzCzH4UQKk48714ze8WJ/77YzPab\n2UXj2vdO0f46juM8zT579jlr/YnHi83s783sthBC4YnHfmhmmWa2xMxKzeyrU7nTzguP30A5p4N/\niaKoLoqigSiKbo2iqCGKorEoin5iZnvM7OwTz7vXjt8omR2fsL4wru03UI7jTDmTzFnNZva1KIqG\nTzy228w2nLjBepWZ3RhFUceJx33++hPDb6Cc00Hd0/8RQviLEMLmEEJnCKHTzJba8b/ezI7fIF14\nYvKZbmY/NbPzQwi1dvyvv81TuteO4/zJM8mcdSSKomjc0w+ZWaWZVZtZexRFHVO8u86LCL+Bck4H\nkZlZCKHGzL5tZh80s6IoivLNbLuZBTOzKIr2mlm/mX3IzO6LoqjbzBrN7L1m9kAURWMvwL47jvMn\nymRzlpnNDCGEcS+ZZWYNdvyPxsIQQv5U7q/z4sJvoJzTSZYdv5lqMTMLIbzLjv81N5577fhk9fTX\n3feg7TiOM1VMNmeVmtlfhRBSQgjXmNlZZnZnFEVHzexXZvZvIYSCE49fZM6fFH4D5Zw2oijaaWb/\naGYPm1mTmS0zswfxtHvNLMfM7nuWtuM4zpRwCnPWI2Y238xazezzZnZ1FEVtJx671syGzWyXHXel\nPjxFu+28SAi6vOs4juM4TgjhnWb27iiKLnih98V5ceLfQDmO4ziO4ySJ30A5juM4juMkiS/hOY7j\nOI7jJMnz+gYqhPDnIYTdIYS9IYSPnq6dchzHmQp8DnMc57nynL+BCiFMN7OnzOxyM6s3s8fM7K0n\nftXgOI7zosbnMMdxng8znsdrzzazvVEU7TczCyHcYmZXmdmzTj7FxcVRTU3tM+1jI5qbOIZ7OYkv\nM7Pp0/QfRkbjN398TmT6nGD6+PTpeD5uKHl/OYqdnIHXjyEKkseQ6D34lGk8hknucUew0WnY6Bje\nYMa0yb94HMVrsEuxfuQxcRPcJ567RP000euHR+OZm2kpulH22xj7fZKNsl9TZ+j781zHXx8/cdwk\nj8smGa+TvV9sH9DPvD4SwWuA45Hjif04/ul1hw9ZW2vr5Bt9YUhqDisoLIoqqmrG/Yv2wxDmszSM\nF/YTx6NZgvEw8fCIXZeEW+A1wc2dyp/TvNan8/zj2udhcvZhv3GfBkZGpZ2bloL3j+81t8l95DZG\nMJ9Mx0HwmPjZxfMWP436D0OjekxmZukzpk/4noPD+prYfIR+4PyTOj25BadjCebY+LmeeEzzGNiP\nk32+8phSpvOaiu3ipOOTR8VriGNn59YnWqMoKolv6fndQM20cSU87PhfcOsnekFNTa09+Mjjz7Tr\n2vrl8f4hHSDpqTqg8jP1wmnuHoptIyddD2myG56CrFRpD+PC4MXdMzgi7cIs3afBYVxYCWa4rv5h\naadgn3Iz9D25D6StR/shM037oA/7XJyjx5xgHre+IX1NeoqeixRcvJ19x6SdhX3IStPXt/bo83le\n+GGTgZujxq74uZ9bmiVt9huPiR9w7If2Xt3HWcWZ0h44puOVF3tHn55ns/i55rniBMTn81TxGDje\n23AMHO+JPnz44cB9HJpkIh8/Vi67aMIp4YUmqTmsoqrGbr7jZN4rbzT3dfRKe25BtrTZT724Ls3i\nfc3pg6eLfzQQjgeeW17Xif4wIZ2YvzjnZqPN64T9sK+1T9pp+JDc0dYt7cvmlE74/on+LQdzKq+b\nxu5Baeel6/NzMvSYDrfrZ1cGbn5m4Bh4HR/o0GM2M1tYkiPtTHz+7WzskXZt4cTzUVu/XvvVBfp8\nwrmnvqs/9pyclIn7hWM6A8fA8c3x2DOgY6t3WN+vKl+Pgf1qFv985XjkNtNwDXB+W1qVcyi2kROc\n8V/hhRDeG0J4PITweEtry5nenOM4zmlj/PzV2d76Qu+O4zgvIp7PDdQRO15Q8WmqTvybEEXRt6Io\nWhtF0dqS4oTfgjmO47wQTDqHjZ+/8guLzXEc52mezxLeY2Y2P4Qw245POm8xs7dN9IJjI2OybFdd\npF/H/fBx/abs9i1N0n7n+ippf/vBw7FtrJ5dIO0DLfo15OuX69e/s3J02eepDv26uGNAv0J8ol6/\npv+L1ZXSPtStX83mpupXnmZmffhachBfmw8O61epOWl6n9s+oF8xZuJr/PkFekyp0/Qrypu3NUh7\nXZV+dWxm9osd+m1hRV66tIuxdHmwXb8CJ6uqdJ821mk/Li6b+OvlsmxdevrZ5qbYcz5wXq20//He\nfdJ+1znV0v7YTVuk/eV3rJT2bdubpc1z/VBdp7RnF2of7W0diO1jOpcisZR5uFXH61XL9Y+OWzc1\nSvs9586S9rwiXTa6a7+ex258xX7PDj1GM7OLFus1sqhEz81DB/UaWVCix31+VdEz/z00/KKuD53k\nHBbJsh2XmatztJ+2t3RJe1FhrrTreuJLJKWj2pf0UBZX6HvUt+sYaxvQpW3OP1y64hILHTkuAZqZ\n1ZbotZyO9zyIMczley5vrajKk/YwvL0iLDtzmYjL0mZmh7H8FFMQsPSTCjmnpU/7kUul9LLKcvS8\n5WJpizoBl/zM4ktLD9XpN55z8vTa/sB/bZX2996+Wto8d9RT6FTVFE88B5vFVYsjnTr+btmm89MH\nzqmR9uaGDmmfVaLjubIgQ9o8hg6oIrzGzMyWl2p9Zy4Zc4mPuslgEr+re843UFEUjYQQPmhmvzGz\n6Wb23SiKdjzX93Mcx5lKfA5zHOf58Hy+gbIoiu40sztP0744juNMKT6HOY7zXPFSLo7jOI7jOEny\nvL6BSpaxSKMK6Dxdu1bXSw926Dp0M36W+dqVZbFtcD1+fjHcnYw0afMnjktLdP20Fz99z4IzUJyp\n75cziXNgZrYN67aV6foe+zt1/X5unjpKY5H+nJWe1q/3tEn7hrXq/pxTrevOdLLMzG675UFp3/T5\nN0j7cJeufS+vVC+ie1DX12fn6uOmu2QL8vUYj/br+9MZ2LAs/oOEfPxU+e3r1FmqzNL19S+9Y4W0\nmRm2qkqdA57rDfPVFdrSok7UnCIde2Zmvfip8VnF6uyVL62QNn9iG9YgBgGP8yflS4u1X3mMlblx\nf4TaSxmOex6uqcLMuOf3cmRoZEyiCug88VzlpOq5+P0hdVo2zI/PX21wPCrzdMzSW5kBZ6kW/mM8\nU46xLjo/5WboMSQKWj7Sob5jeb6Ohz0dOj+try6SNuNBOga0/dPt6tF85OK50k5P0X16qkW3Z2b2\nlus+J+3tv/mytBlDkAMPph9zKt2wvNSJf87fjdczQqWmEPOhxbOozqvWHy3Q3fnmm3T+aujQOZPj\nkdEzcxD7sr1e3Ub6mmZm3fBvKzA+P/oKPVfsF34e0mkqgutK5yofvtu61MLYPnJ8ZWFOZDYe+5VR\nRRPh30A5juM4juMkid9AOY7jOI7jJInfQDmO4ziO4yTJlDpQIWh5FuY80Xn65OULpH37Ns3pfOdf\n/t/YNv76E++S9kO7NQdn3TxdV377cvVkmnp1fb9vRNdD79urnkttnnoQ+7viEf3k2Iiuwd65U92I\n9bWai/Jku65N37VTHad5ZerqrICPVA+namODOgNrKuM5UB+68TJp33NAjzsfrkT/MV2/p5uxpVmP\nYW+L9vOuZm0z/2NJua613/OU5omYma2Av3bz40el/dFXzpP2Q4d1n+YUqevzhR9slPa5H7tc2jdt\n0/dv7tJjKM2LO1BZqRP/zbKtWfOxKnPVtfjVDj33q2apz8YMnfsPaz+xUsfOI/EclUqUiEiFh9DW\nr9fE4U69bquzT74+UamYlyppM6ZJeRZm0NB5qs3X63IWPMCLP/4/sW385tOvlvbGhnZp1+A9SnN0\nzNJfY84TfQ+UlbNulNLoTFCOiM7TgWad85aV6vzFa/kI8q8WwNP7ILKDuE88ppVVet2bmT1x5xel\nzeyoKuQNEeZGMaOJGWAN8MKYfcVSMonK+FQV6j49cEA/F1ZV6nH2ofQZ84w++etd0v7Xq5dLe/Mh\nndMb+/UY5hfFPxfoING53Iv5i+OT4+9on3pbg+jnSow1lnujE2gWr7/H+asS/cwyZIm85WfDv4Fy\nHMdxHMdJEr+BchzHcRzHSRK/gXIcx3Ecx0mSkCjn40yxYtWa6K57//hM+37U6WLOUxHWja9aNlPa\n//HIgdg2qlCTKG06sjBQ86gGvscgandx7Xt/p67xLivT9X6u0SZyQDoG9Tib+tUhOYC6cq+s0RyV\nkUj3ievI/3yX1oD70fVn6/u36TEUpMezgDY2qTtTkaX9yn4MpuvMdKCmY126eUCPMbZujffPTp24\ntpSZ2VLUCWtBnbk61CnsRz2rrBm6jR0t2k9/Nldzn5r79BgK0lCzK0G+Vipyd1jrbHgMDkCOrtfv\nakMdukL1FOhB7GxWT4d1Efd1xp29ecgS4nEd6tHXMKOrJu/k69/2mottx9ZNenJfoixZsTr66Z33\nPdPmtc6cp8tna1YZM5kSeTC8bkrz1CHha+ji8PXM/mE9NLo6fD/6R4ngPv3PHq2v+LblOm9nwmFq\ngjt42cdvl/aW//smadPzY0aTmdlTzep5ViGviPlXrI0XqyOHbfKYOc/n4bOLnyMF2fE5NwO5S5m4\nlm9+Qmu/Li7S+Y5zST/83crsifuAGUyJ5ljWletDP7T06mfZ7GKdSzrhQHG8sh+Z2YThmTCzKR+5\ndMzD6sGYZj/w3J43v2BjFEVrYxsy/wbKcRzHcRwnafwGynEcx3EcJ0n8BspxHMdxHCdJpjQHamQ0\nsubuk2uk335Q13RZ2445T1/+yvuk/e71s2PbuOa7j0mbjtcrFmkOFF2eziH1ZnrgsfznQ3XS/tDF\ntdLej3pEWWnxe9StDZqDwjXXxRW6bvzDLQ3SZj0z+kfvu1T7hdkbt2zVWlMz89WzMDNr7NZ+GDym\nLk01sjTq2vW4STkykbhez/X/g63aR4XZuo9b9msekpnZpzecJe0v/36vtN91nhbg+86Dei4vX6KO\n02c/d4u0z//mX0r7q/fsl3Z5vvZJOlwPM7MhOHYFWbpen49clex09bAe3KO5QO85R1+fMaDbvH2H\neobTp9NhiDsuB/OR65SvbsSWI7pPrPP1/nE5PiNjcY/ipcrYWCTXah3yjFjbjjlPt3/8z6XNOpxm\n8WwpelOluXodsO5XCpwmZia19ei5pSMVMLcwV8rseD+Mh8fxjhXqPB2F41SWq3NBHpyVx756tbRz\n4ROx5hv9IjOzWtSaG0JeUH4WatdhjuSYZi4Ur1u6Y/14Pb3X5j49D2Zmc+ELPVGvOU2ry7Ru5t5O\n9byWlqiP+5ZvbJL2b///i6V95279HFhWrK/neTGLf1bRiUqHD0mHjmOnIEfnlsYu7RfqbXSi+Dlk\nFvfVuI8juCY6kHVGR28i/Bsox3Ecx3GcJPEbKMdxHMdxnCTxGyjHcRzHcZwk8Rsox3Ecx3GcJJlS\niXz6tCDFB1fPVikuHbIXCwMzJJPCuJnZrdevk/b7b92KbaiVRmn8fhRYXFymktpFC1VCp2RZkKld\n2jsUL3Z4Qa0GoO1oVhm1AmJdLQoqHoaUmQNxdG6eFjFl0Ny6WRq+OA9FT83MfrBJCze/Yr4WsoxJ\nk5Cj61o1bLEI0mYR+ikF+1gUk6tRnDMtLvqlIzR1cbXu8/git2ZmZ88tlPZTOA/v+/Abpb0H0ubb\nz9ZC1AzJ3NoYD6ksx7nNxXF1oFDvYhRabe1V4ZEBgCzeubpaX8+xsLMpLv/PL9HxVpqp74la2DaA\nQtL546TfRCGHL1WmhSDhhqWj2k9tKErKwsAUYCmMm8VF4MYeBs7q83ciWPXROhX8r11eIe1ChCWy\nADbDGw8iONjMbPVMnbfbILIzmJCFeyl9p0LQ5usZlsh9LM6JzwV379VC9RfP0R+IUGbuguz8QL3+\nWONcHHNluh4Tf6xEeT9vbOJwR7MExYFT9DjT8UObmVk6n/14m/7Y6Kb3nSPtu/dpwOnFtRr0mok5\n9UiCHwaxmDCv71aEQpfn6WcdgzQpcFNcZ/DryHTtZ77eLN73PDfcZ0rmM6af+pzl30A5juM4juMk\nid9AOY7jOI7jJInfQDmO4ziO4yTJlDpQkUVSpPFAizon84vVKXhot4YAXlyr69CJCiHTefrGNcul\nffk/PyDtT29YJO2SbF2DRd6j1XVijTdXn0+XpzQrXjRyR7O6MYfbdK25Kk9fs71R+6keQXJLK9Vh\nas/SfWzuV89hU716DUOUWizuIWw9qvvA4sB5WD9vT4+HsI3n3j3qmqVh3bodgX+ra9QNeXRfPEjz\nsjladLm5W4+bK9scfxuWqN/2yx1aHPZ87MOvduk+FGD9/vEE+7h+vm6je1CPewgD7rEG9WQefkr3\n6dxq3aetTdqvu1u0DxiKefN/PxHbx3e8YZW002bqWNjbouOPTkFd98l+ZWDqS5qgDhKPrRIFazc2\nqEdzfo2ee4ZkmsWdp3J4n9/frG7imxeXSzsN1y2dlRQ8PoI5lAVls9PVIzQz6z+mrg6nYRYobkY4\n4iheUAxvj0Vsj2K+Y6glQzLNzM5CoV0GW3Kf55ZqiCXhPta1Yz6cpChuHubDI11xv6gWhe2Hhic+\nlxwr719fI226Yyw+XNepx1CWrWNtW2vc0XtljrpkLO7LwuJHO3UfWfh+eYWOryeOaBH7RSW6zzkI\nbf3bO3bG9vHjl8yXNr2qAfi6dKBYEHki/Bsox3Ecx3GcJPEbKMdxHMdxnCTxGyjHcRzHcZwkmVIH\nKliQjIXXL9f11OIMXWdeN2/iwr8sDGwWz3mi8/Tbv75A2nds1+yMPOTyZMPNqUbh3UUFukbb2K9r\nvNkp8S5eUKxr3YUZ+hz6ReuqNMtnVaWu1zNHisWF5xeqI7WrQJ+/olSPwcysDXkdlbm6/t7ap+vr\nzCNaNlO3WQ634iiKFS8qVX8kP119t34Uda4t1T4xi+dAzUY/c617ZbUed2G67mMpCiCXZWqbRZ8/\n++8PSvvqq1bG9rEQ+VcsopyVquv1zPTqg3+Sn6b7PDMHmTvwdNLgKLzr6tWxfSzN0X3gGF5aof1K\np6A2/2S/pE0/9cKcL3oidWcWV+j4GYSLU5Or44OFWFkY2Cye80Tn6bqVWqj3oXr17Dj/9WGbEfyk\nIng19GZGE1QTZrFVxIRZS7c6JAW49nMx3+2HE8q8owrkSLXi/ZltZWZ2CH4jc+tY5JbHmQHPio93\nHdP5azay9CoLdK44hOLoLAhvZtafIDNwPIO49gswX9EdY65UGua/zBl6Hs7+8E+l/d2P/1lsH9hv\nhJ/RVSj2S7eW/To7X6+Z7LSJM50+9sp5sX1gP3CfZ+AiG8Q+lKPY9UT4N1CO4ziO4zhJ4jdQjuM4\njuM4SeI3UI7jOI7jOEkSEmUpnSlWrVkb3fvgo8+0d9RrHadsZDywDk4O1s4bkDFhFq9tl52qr+kY\n1Mdfs1Trmd2+TZ2Dmhxdk2V2C90frunymMziLkQ/3Al6CQNY+2atH26TmSTMMGlEvyWq/cN9ZPbK\nMNwaHgPzaFj7iec2Dd7DMOqGsXYVs63MzGqwfl6PrJWzytWbOoB6fVz7bkYWVWGmnhdmoHCfE11b\n9LB4bgtw7vuQX8PnM+OEr29HnTKet47+uNPAmpSTnbsUPL9iXO3GKy4+x7Y8sfFlURBv2YrV0W13\nnXQqWYeLbgVri3F8sB/NzLYje2dBvo7ZTc2a83VelWaffXdTvbRfi9qd1fnqrzUiKy0Tvht9J7P4\nGGJtu9wMHZP0quh+jeDa7oGzwmwqOncjCbLGhoYn/uzgdcQ2XR2eW+Y88RrhgO9AncT+kbjvxG0M\nj+kxTHbuOH/RqWJ+V1mengeOz0RlLDke2nEN0G/rwvzCfuUcyc9LelscSzxvZvHPQ8650zBxc/7i\nZ/rc0syNURStjW3I/Bsox3Ecx3GcpJn0BiqE8N0QQnMIYfu4fysMIfw2hLDnxP8XTPQejuM4LxQ+\nhzmOcyY4lW+gvmdmf45/+6iZ3R1F0Xwzu/tE23Ec58XI98znMMdxTjOT5kBFUXRfCKEW/3yVmb3i\nxH9/38zuMbOPnMJ7ybr/Ux3qQC0t0bo4Tb26xpsyQ9eA6TuZmd1/SB0B1rZjzhOdp6uWac7K/Xu0\nHh9dn1JkA3GfEsSoWM8xXRdmVk/qANZ9h/X5HdB/6BCwHhGdqZY+dXsGEqzHj0a6T+nTdagwG6hl\nQN8zHWvd2SN6Hup6NRelKlvzQphlxdyVzqG4u1Mxou/RhEyuyn49V904D+l92k8NqNtUAAeqBY5U\nL7Kq6DSYxbNXhka177lez3pXPFf0FrLS9P3pDJBE11C+TVw/rfeYvmcXPKvxDtSLgdM5h42nDWO+\ntkAdPF77HA8paXG/6NE6rVNJl5A5T3Serl9dJW26jIS5PfSJhkfjY5jjgf4P4TswL4vOCvOLoDbG\nvJmG7nhduVhGEpwoujb0uLjP9B1bMYdW5urck445dwDXeU5q/KOXyiTndfo+9Ht5DPR16UsOok9Y\nU5Deq1l8vmE/0S/iuSzI0rHT0a/jk/tInzcT8xsfTwTHJ8dbG+bx6iK9z5iI5+pAlUVRdPTEfzea\nWdlzfB/HcZwXAp/DHMd5XjxviTw6/ufAs/6UL4Tw3hDC4yGEx9taW5/taY7jOC8IE81h4+ev9naf\nvxzHOclzvYFqCiFUmJmd+P/mZ3tiFEXfiqJobRRFa4uK46VXHMdxXgBOaQ4bP38VFvr85TjOSZ5r\nLbxfmNl1ZvZ/Tvz/7afyoijSOjUdA7r+2YvMm74RbXONt2c4vr6/uEzXohkRwtp2zHmi83Th/BJp\nf+JXu6TdiWO473F1Em7csCC2j5XIQdl0RL2HDdgmvZchHFRLvzooS4u1RldTl67x7u3U7a0pi/8A\naTPyZlr6NDNpaanWftrS2CPtRSW6jtwF34jOUzvyuQ4jw6kcWVa9CfI/mOeROn3izKUmeAzMZtmN\nelqzsvWYRiEt8BhHx+L5NPwXZtrQkeJ7cp/Ls9Q3aupSZ+rxxg5pz87TY6jrifsj7LeOId3mwc74\na8Yzq/3k48wMehGR9BwWmfoTuahbSOeE7iHnLz5uZnbt8gpp5zMXDE5TdY6eTzpPdH2O4Lr66r37\npf3HP2r7729YH9vHS2br/LSnVa/9VTPVZeVXe/T8Ovsmzn1qxpim97KiSrdnZtYAUZQ+7fxMzddq\nH9D5Z2aezk/0hdbM0jmzpUdf34Y2nVG6PmZxt6zEdM5jphLhuWfmEvutHK4iM+M4ns3iWVLMqWPe\nFjOVCDPBmFHIPilFdhVrHJqZZcEtZF4bawrS66pr03l/Ik4lxuDHZvawmS0MIdSHEG6w45PO5SGE\nPWZ22Ym24zjOiw6fwxzHOROcyq/w3vosD116mvfFcRzntONzmOM4ZwJPInccx3Ecx0mS5+pAPSdG\nxyLJpXmiXl2cLDgB9+1VD+fKpfp+//lQXWwbF6H2U10nMh7ydQ11LmpNMeeJztPnXrVI2l+7b5+0\ns8+vkXbfsbgD8oWf63uuXKhOwcNH1FsZgjuxv1U9hkI4A0e6dC37ygWl0t7douvMT9Srt2VmVlOo\n/dSOvI6HDmvNrroO3afpWJvuQR7IY5Gee+bb7D6qj6+tzZP29gZ93MysBlksd+1ul/YVC/X5O5p0\nrTsba+f3P6k+3EJ4Xdsa1QvrGtRj7O6PZyz97n4dL+vWVEv7SJW+hkv8TxzUayIPuSgVWdoHv9yq\nbnRLux5zWTFCdswsivS4mb1Cl6cMvsjKspPOATNXXspEkR4763QxnyhWBwxOCfNnzOLXMh2QCGM0\nM23izBo6T0WZel2/H/PV310yX9r0Lc3MvvGozrs3rtMxzOwf9ks3vFEe885GzQek40SH5Y8H22L7\neOFcnVPz+9U5Ym3N0mz1gegoHevWc9WMNl0cjnu6QYnyi+gXEfqE3EeOt344wsyNmiwjjNe5mdnf\n/0Y/u961XnPHeLVzzHObOaibyPHe1KefVb/co/PZG5eoM2hm9mSTjp9+uNS1uTrnsX5fMnOWfwPl\nOI7jOI6TJH4D5TiO4ziOkyR+A+U4juM4jpMkU+pAzZgerDDr5JrnX6yulMeLsT5fi8ya6nxtf+ji\n2tg2uHxZnqtrrIsKNCOJORWx2nZYr6fz9OGL5kr72388IO2zitSxMjPbu1A9lIvnqd/DfWRuyuY8\n9WBY92lRsW6Tr19cqs7K0mLdvlm8Pl/zgK5Fd6EW3fmz1FNg7skYVsdZO68Ix7CmUo+BmTuLS+Lu\nTjmypW48e5a06Qzkpeo2izK0vaxMtzE3X7Ov5qHN9frhBDlQGxaro8daZ0vK9Fwwm+Wy2UXSnhH0\n9QVZeozXn6t+SjnG927UozQzy0/TfuA+MrOL/kflOCeKTsNLmRC0PhhznJi7k4aoH0biMLfMLJ55\nNAJ/qAi5UC29eh2xth1znug8zczVOfWhevWJmClnZtaG+oxtfToeSpHZxiyqPc3qL9KRWjFTrwHm\nt+1t0dfPLdTr0MysZ0Dnpw2ilqEAACAASURBVFb4Zq3wE2sKtB+4TTpLvC45t7AWXj+8sETXRT8y\nlWaX6vzT1a+vYTYV9yEn0vZkGWGt9Lpie2j2ycviuYbjWVCh83Z9O3xdzE8HkLVHr7Acbto7Vul4\n7OyLe6Yzc/RzgDUFJ3MVE2V0PRsvn9nNcRzHcRxnivAbKMdxHMdxnCTxGyjHcRzHcZwkmVIHamxM\n120PdWuOTg48l/1d+nhRhq6t7++I1+QqyEQtHqxdN/bra7JSdf28c0jXVFnbjjlPdJ7ec85sad+2\nNZ6xdNkCraP0GPKwMukPYc22tU/XsvFwbK17slyLh4+0x/6tJl/XkXdhrTo3Xdf4d/TpMXB9vh0u\n2cpKdQ56sP7PtXDWPWzujdeFKs/Ufa7v1X1OT9H1+Y1H1f9ZU6Hr61uR85STouOzoQ9jKUX7pGso\nnrPS0qv/dhaypQ626zaZS7a1Sft5ZbkeE52+DvhKe5EDxfNkZmYoLUbHqRc+B8dXY/dJR2bkxVsL\nL2ki0yweejG5GXr+u+HhzMD4CLHUnHjmFuvC9eDa5lzB/mZtO+Y80Xk6r0odu7b+eFbVp+DB7G/X\nMZk/otcJc+xyIYfRJeN0Rc+FvtLu1rjHd06NHgf3oTRLP0uYwdSB2nhPtmm9P9YDZGZSAVy1o6jx\nRi/HzCwN44PzOh27drxneZ76QoOYf5gLRd+OmUxDw/Fcqr4hPc6ZhTrnMh+LeVuNqMvKnKhYPzLj\nkE4VHjeLu1s8t5nIwxrEcR7t1n6ZCP8GynEcx3EcJ0n8BspxHMdxHCdJ/AbKcRzHcRwnSabUgQrB\nbNq4NU9m+9B7IXSBstLiz6efUYq1aOYTMQuDS9M3btD1fta2Y84Tnac3LNdaQWZmWw5pjlP/iO5z\nHvolY4aujadN1/bQqL6eTsEQPJf8dH3/KuRmmMVr2c3K136kF1OereeiKF0dA7pl9JV6htUXaezX\ndej5edrPGTPU5Tm+T9pOhTPAtfAqHNPHbt0m7XdfPmfC90/HeWGuFDPFju+D+ho/29ok7Q+frw5d\nHjKZWNepPAu5ZejnbtTnW1WmnlfbYNxxKYZryKypw6ae1iiuy/xxLsX0aS/fv9HofjFfprNPx3Rm\nml6HidTEg53qE2Wnq5DGbWbiWh8e1UH69zeslzZr2zHnic4Ta+eZmZXm6r/Ry+J1wn1MT9ExQe8l\nB5cN+4mfAzV58Uw4Okb8bGE/8nOgJEfd2Dx4W8XIumKWUBtyoopz9DpOVAuvG+/RB4epEc4T89nO\n/dufS/t3n3mN7iOy+/g5kp2OzLEEfhFrK37qN09p+zJ17NivrOc3gvOy8ajWgS09pv08r0TPS6J+\n5GfTDHihzPiKeVcZ8eN+Nl6+s5vjOI7jOM4Zwm+gHMdxHMdxksRvoBzHcRzHcZLEb6Acx3Ecx3GS\nZEol8tGxSGS7PgR7bWvpkvaxEZXaGAq4tSEuEl9Qq1LkjmYVXhcUawgbQyd7jqloVwlh8gs/3yVt\nFgZmSCaFcTOzFTUqhv7LwwelfeUSFRbvPahiXQsExRyIenUIKzu7QrfHIreU2M3ifT0AEb0LcjID\n0UbzEaDWo+93oFNlxIIMPYZ9bSpMFkKm3onzamZWna3ntqFX36MiS8V1/vXwkasWSnvTERV615Xr\nuaW834KCy082x4NeGyCCrqzW8UrR84E6PfeN3dqPuWfpWCmDVL4b+/DYIb3GFlfEi13f2aThiv91\n873Svv7dl0m7KEvP3dLik2OFwu9LmdGxyDrHzV+1KGh9pAPBhvl6LhisyZBBM7PVM3WMxUMAJw7r\nZJFaBj5+49E6abMwMEMyKYybmdUhzLCuR+fAFZhvtjfqHDgdP0ooRCHxnQjGZNFuBka2JygoS7WY\nwZac96dh/mIBdorxDIykGE+3mSGZiUIqszCP81yW4ri5zXv/95XS5py8GD8gYZ9Qrq5ri89fXfh8\n/PD5tRPu00OHdC6pwhydi3l/eakWkm5AqOWv9+iPbq5aXBnbx9/v1ee890Nf18d/+FFp8wcGHAsT\n4d9AOY7jOI7jJInfQDmO4ziO4ySJ30A5juM4juMkydQGaZoWOx1EqFYlwhfv3Nkq7QIUO+Q6tpnZ\njmZdjz+MddxCrLn25yBUC/tED2blQnUKLp6na7YsDJzIL6Lz9J23rJT2V+7ZK22GIR5p02Pcu1+L\nAb8H4Z/ZKJ54x2Parww7MzObmafn4tio+ho7j6in8PCjB6X9gWv0mA7gPMwrUR+JBZJ5zAx8bOuL\nn3ueu5i3gHDOrUe1HxeUqmNAX6kPIZaP1GsfZMFPYdvMrBJeDBUhFkBmseFJ6kLHguV6BtVZmANv\nZ39r3CNcUKbPedt1r5R2Z786J/RFusd5XAzZfCkzPQTxDdNx3HSeDsDTY6HnRNcdAxjZfcy1ZAgg\nXZs9rVoE98Z11bo9+EMsDMyQTLO48zS3AAXZ8Z7TcCF2IOz1hxuPSPt67GMJPKzHDqkX2NQfd3Uu\nml0qbQZr7mrTa/eb9x2S9rcwJx9AYfvVleqqMSCS1yHPE8MezeLeVH6mft491Yhzw+BgjEcWyc2c\npuPtEK59+kileXH/LQfP4XF2Igx0bVWhtOlI0btiv0yHx3rhrGJp9yco2H4envOjb/61bgPPZ9Bm\n/1D8M/vZ8G+gHMdxHMdxksRvoBzHcRzHcZLEb6Acx3Ecx3GSZEodqGnTguWO85gGh3Vden+nrsmu\nr1W/6EC7rocurogXkaxA0caqPBRxxBprEbIwUgf0nnLDfHWeHj6i6++LCjRbIxPFilkY2Cye80Tn\n6X+9Yp60f/LEYWkXInfn3Hm6zlzXqY5Bb4WuE18wV3NaBpHxZGb2pZs2SfvbH7pQ2gWZKL6JjJJB\nrPm/bon24+42dQpm56sTVYT3Z4HbmXm61m5mlosiyZ0DupZdk6Pndkm5brOhW99zRZVmJOUjr6am\nQPepCEUoT8X/GYIjNytHx/RTneqw0OHrRi5LeaTH9OrF6gOw4O3corjnkIUxXIvjbIPnkJGKvJrs\nk89PeRkVE542Tb2lg3BI9nTouVqGTJsfb2uQ9jtWzIxtYwayf7LS1GlqQf5QbkZ8fhnPqpl6rfex\n2DqK4uaP6PslUHViOU90nngMldk6JnNSdBssoH3z9kZpswD8zDx9PxbYNjO74JO/kva2r7xW2rP7\n1dt674WzpP1Ui57LNcjnakLWHvOy6H2NwJFiMWOzuE+0+6juQw98n7JcnXM3NqgLu26mfi7QseJc\nwNypRIV6s9Iw/wywYLY+vhf9WJ2vTmcdPvOLIfnNL9E5mF4Xs6zM4l4UHT26iPSucjI8B8pxHMdx\nHOeM4TdQjuM4juM4SeI3UI7jOI7jOEkypQ5UFJkNjXNjctL0/m1unq53PtmuWR2vrCmS9g+3qFNg\nZlaLLJbtjbrGug5eC3MoeoZ1TXcAjsoQ3B5mb7D2V8aMeBYQa9sx84jO05tX6fr8Nx/aL23mWFy5\nsEzaI8hwykf+TF5u3KP42vvPlTazW+YX6Fr2DCwbFyLD5HC3ZrVUwL1gfb4+5oNkTb4unYHcJXoG\nXNJnv9+zq0Xa151TJe22fvUeeo/pPg+P6uMH27VtZladr2v2Regn5l199oebpf3uK5dIe06BHnMP\naukdQ72+HzxUL+0rV1XE9rEFGVsd/douz9F9Hjg2ecbNy4GxSOcL+knrq3V+4vh723J1no52qdNp\nZlZVoH5PM1ybgmwdP13w0djzNG3ovTCLivMba++ZxWvb0feh80Qnit4pXZvP/pnm2NWj9l4ePMBl\n5eqamZk9+oUN0mY+0Wzkq/Fccl6fzHnivM9cqPjnRGyXLS9z4pxD9tMg5sjvPqh1Dje8W6/tXQ3q\nI3Ef2pFB1twXn78qc1mPT/uNPtyVn/iFtB/6p2uknQtHuAXbzIHj96nf7Jb2V167OLaPjThXT8FN\nXFOhPls8S+3Uv1fyb6Acx3Ecx3GSZNIbqBBCdQjhDyGEnSGEHSGEvz7x74UhhN+GEPac+P+Cyd7L\ncRxnKvH5y3GcM8WpfAM1Ymb/XxRFi83sHDP7QAhhsZl91MzujqJovpndfaLtOI7zYsLnL8dxzgiT\nOlBRFB01s6Mn/rsnhPCkmc00s6vM7BUnnvZ9M7vHzD6SzMbbkdMzFula5V0726S96AL1l6LYCr/Z\nYXgF9R26fr6qUnN26M10QEsYwlr2/lZ9v8156gOwplva9LhD0IK1Zta2Y84Tnacbz5sj7bM/8ztp\nz3mTHuMgPJiPfHejtK++YmFsH9PgVXH9va5dM0fKkQNF9rbpunQ5ahCWZOsx37dHPbHspdqP+9vi\n/gizVtrh7jBjhOPt2vXqqDxwQB28d67S8cdMHYNH0dEfz6piBgmzquizfeFda6S9qUHzs5jZ1Ih6\nf3ds07qHV6+rlPYjOEYzs1Q4ALMK9Nzuao7XHhvPuooXTy280zl/TTN1Wej20CE5gppxy5GfxBwf\ns7iPwf5jvbK0SeqfxeoUDug1sadZ66vlpqlzwtplZmbTg/4b/UjmPNF5onvztfsPSPtTl82Xdmuv\nzh1/+RP1Aj94ieZImZktLlEviv7jria99msLdc7kuW0d0H1gnTo6VFsbu6S9pFTzAjlXmZmlYpus\nazizUN0y5vf92zUrpE0XqAJ+HX0l+kbMnTKL+40cb22ok/nEv75F2vTlCrP1mPcf0vHYcUTfj84T\n3TYzrcVpZragYOIsKXrQo2Pxz+xnIykHKoRQa2arzOwRMys7MTmZmTWaWdmzvMxxHOcFx+cvx3FO\nJ6d8AxVCyDazn5nZh6Mokj9bo+M/7Uj4p2YI4b0hhMdDCI+3t7UkeorjOM4Z5bTMX+2tiZ7iOM6f\nKKd0AxVCSLHjk89NURTdduKfm0IIFScerzCz5kSvjaLoW1EUrY2iaG1hUUmipziO45wxTtv8VVic\n6CmO4/yJMqkDFY4ven7HzJ6Mouifxj30CzO7zsz+z4n/v32y9xoZG7O2npPrsplYX+/A+vy8Mq1h\nc7RP3YsQSz0xy8Fa9NJKfY8dzeolLMFa+QgW6FuwpluIHJYC1Eej8jEE/8jMLAfZK3v3q0/E2nb0\nYug8Pfqpy6T9D3dpVgZrbi1dUi7tA/AgzMwqkfNUmq3r47d+5dvSzlx+vrSvfcNKaS+r0PV31uuj\nEnDePP1RFB0s5tmYmQ2PMvdJX0O/pLFH18pnwePqwrnvGMRYQL2+IWy/LDdepykNngPPbTbqynXB\nQ+Ax8Bg5nmtK1PXIgfNXlBPfR+aE0bNZUq5jowcu2Ixx5+qFToQ6nfPX0MiY7Ws96aCtqNK+7hjQ\n8bGgWN2LJviZzP0xM0uF91KMvLT9zerAlSCPiNlTnX06xjl/8TqiE8rxZmZWiDnvhxuPSJu17Xjt\n0nn6q/NqpX3/QV2peM1i9fbecb7ms/2xTse4mdnsPJ336Sy98drPSHvhVa+X9r9fq+7hWWXqMLHe\n2mik/XYuMgv7EvhEhG4OvS26OswA47lldhXPJZ0nUpITr5M5AzvFz8ucVJ076IkyV4xj4/xa/ZKl\nA14ha/Elypyjv8bjri3W+asdLljMbZ2AUwnSPN/MrjWzbSGEp+29v7PjE89PQwg3mNkhM3vTKW/V\ncRxnavD5y3GcM8Kp/ArvAXv2PyQvPb274ziOc/rw+ctxnDOFJ5E7juM4juMkyZTWwpsWgmWOW8Oc\nX6DZG7/eo7lPK5DZ9M937ZP2+y6N53/Mxdp3e5auA9Ob4hosa9ctLda17yNdul66CJ4D6xfRKTAz\nq8Pa9Hs2aO0n+kGsbcecJzpPf49cp8Ot6n199s8XSXtjk2YumZn95FGtM5g3T9f0f/S9j0t7S6N6\nCItLdR8L0+KuzXh43ri2ng4PZ6A67mYwY2l9tZ47+kZvPEv7tfuYOgVvWqmuWGkWfJNJ6h72DSfK\nUbEJn7OsVLOC2vsndsUyZ+glTL/ughr1dDKQS7agJFEeDbJa4LzEagoe02PIH5f7w+vrpUwI6rDR\nufvp9kZpf/CcGmlf9nHVrB776tWxbdDfYG065jL1DOiYpb9RBC9mZ6Pmfq2YqeODGU05CeLddrbq\ne1y/rlraN6MfWNuOOU90nngNdOMYr1tbK+3/3qr1Hc3MPvGrJ6X99rPVo9r4yy9Ke2ez5jYxg2kY\n54EZb6wpSEOTbhrbZvGMrhSMhQ74bHPLdI491KLz/EzktzV36+fOEJyr2DFE8WuXztEAPu8WVEzs\n/dHbYs3AAmSGsS4dfSVmYZnFP4OZhcZzx35lP0yEfwPlOI7jOI6TJH4D5TiO4ziOkyR+A+U4juM4\njpMkIVGezpli8fJV0Y9+ce8zbdbaYe5Efaeu6c4pVk+G66lmcedib7u6OfMLdY22PF/XiZnXwSwN\nKh3M3mjBOjPXsc3MeuGMZCM7Y7LH61BjayE8LG5zFnIv/rBbMwNr4aKZxTNH7qanUKJ+Ef2jtGnT\nJ3y8F+7P4Ihu7zd7NRvrrUsr8Pr4uc9N1VwT1jHMhNcwAoeF3tUYTIZ85Kawj7jW3tKnYyHRPtLL\nogPTBf9jJNJj6oG3taddx8bZFZqnlYE+aO2ffB/p3bTCy2K21YJx+W2vvuQ82/LExpeFCDVr0bLo\nb7/zi2faF83SYE1m1NDdYe5TboIcnh74G0dRy5P1zDB8DEPamuGgVBXpXMAxzPpoCVSd2BzILKq6\nNt1nHjdr262cNbHzREeF7g77xCz+s8tb4EldjHPHMU7Xh5+TzBbiZ9lNW49K+0Z4Yonc2H3tmsc3\nt1A/7xq6tV+r8vRcduDc8bOttUcfp+vDen58vlncseTnLZ09nuvibB0r9x/WzxW6t//8huXSZiYd\nHSqzeBYj95F5WzzXrDc5tzRzYxRFa2MbMv8GynEcx3EcJ2n8BspxHMdxHCdJ/AbKcRzHcRwnSaY0\nB2rGtGlWPK721s3bdL3zHOT2bGxQf4kZOrds1bwRM7N1s9QH2lSv68q7CtQRee0CzQKit7K3U1+/\nu0WdgsWl8fX38eSnxz2H4TFdt73jMa3yfsFcdQJYm+wj390obda2Y84TnadXLiyV9g23bDZSmqvr\n5/c8oeeqF2vbb71srrQHh3Uhem6xrn0fbNfXLyjRfnwM+zwzT12zfa3qA5iZvW25elK37mjSx5fp\n4/fXqWc1txD7UK/j78oF2m9/OKS5ZakzdIAeao/7RRUJ6uONZ1GJeg1NGI+HO9RLeOVsdZzWV2r7\nB5v1vC0q0/ff0RCvg5gJl2duEfJkeuFlQZRJHedE0Yl4KZOblmKXzTk5Bpg3k54ycV055kY1dMTH\nMPs+nc4aHMtc+EV0dWL+B5ynvS16/mtQA3MsgSNbjpqRjx3SHLmZeXod5cEp+cuf6HzD2nbMeWrs\n1DmXGU0/2FQX28dXz9Nr9clGnfd/u0Nzor5+tbo29GvpqzHHaQHqthZn6fPpWybKgZpdoO9BP60m\ngas6HjpPrJNZgH3i+KXbNpLIL0KbzjA9QGbj0YW9dI5+/q4q1fmLuU8VGHuJFO7O2LnDPuG6ZD/T\nuZsI/wbKcRzHcRwnSfwGynEcx3EcJ0n8BspxHMdxHCdJptSBMtNckXVV6iuxLtiaSn28ADW5Zuar\nV2NmNi9f15GHRnSRdEXpxPXRBpBHtKZM12SfqNc8kaXFWkvq4SPq1VTlxB2p/pGJaxCxvk9erq5d\nX41adwea1WNgbbuLZpVIm87Td96yMraPX/z9Hmlfc8EsaW+FH/T1m9XL+uQN66Wdl6bHcE6VrmX3\nj+i5v/ESrXNYkqHPL8mKD91yeFv0quiTzML4GYGbVp2PukzIICnN0X2gMnDRHB0bZmaZcAI6h3S9\nvThd96ksk2v+WrOLjkoRaklxH4pwDeWlxfNoyrN0m8x52pvSF3vNeDLHOQYvo1J4NhZF4kuwbtdT\nLXpNrKxSl5F16pglZGZWnKPng5lHzJ1r71VHhFlBK7APfzyo3h6zhnajzl1NXty7oZfS1K/b5LW8\nrFzH4Adxbf+xTvuNte3Or9X5i87Ta+Cxmpm1Id/sulUzpX3XfvVO1/3NbdL+1T+8RtrMDipCZiG9\nm+vXaO4TVR3mTpnFc+ToftE15LXVjDqtBRgrdJo4/ujolebFCyFmYL+b0S+cj0rztJ/6cQ10D+g+\n0zVjhhizqjITzF+8RpgVRfeLJDNn+TdQjuM4juM4SeI3UI7jOI7jOEniN1CO4ziO4zhJ4jdQjuM4\njuM4STKlEvloFEnw1i92aCHB2255UNofuvEyabcNqnDW2B0vdviDTUekzeKsbZD9NiBwbRTFWjc3\nd0q7plCluGMQ1GryWewzbqR14DhmQrT70k2bpP21958r7TSI75UIv2NBxnXlhdJmSCaFcTOzj1wy\nX9ofvG27tM+do3LqyOgCaT92WGXUCxEOuhmFM0uzVRZsH1DRL6VUz+Md21QCNTOrztF+uH+PCv2V\nED8fOgTpt1JfX9ep52lpse5TS6+22/qxz9PiQZrtGH/rZqnE+1Sn7tOiAv3RA/dpTr7uM+mCMLm/\nTcXUHkidZmZjpQiEhPhe16nHxTC7NWVjz/rYS5mxSEP3DndpOONbrvuctJ+484vS3t+m8n1tYVzQ\nvnuvhr+eVaTn/1CLbpPiMX9o09Ch5/vCuSpk96Bw7zk1RdKmuGwWL9R70WydQy/45K+k/egXNkh7\ncYlK5bPz9Br4xK805PICSOQMyaQwbmZWlKnXOoty37i+Rtpnz9R+PtqnYvzSbN1nBppSZmav8Twd\naI3/ECM/Q8/d/k59TmGaPp6O65KCNQMj+4d0r/ijGoryfQlk6yPt2o+1CP5tQb/ML9dzOzqmjxdO\n12NikCyLZTfj/Yuy48HEDI/Fb7Zi54KhpiwuPBH+DZTjOI7jOE6S+A2U4ziO4zhOkvgNlOM4juM4\nTpJMqQM1Lei6KwsD3vT5N0j7ngPqH1Ug4G/wmIYKmpm9Yr66NluPqjNQiWKuXAdOn65d0tKn69Dt\n8FyaB9Qx2AVHYVZ+fI12AEGZxxBg9u0PXSjtjiH1XrjGS38ob556DHcfVNeMhYEZkmkWd57+9Q1L\npf03t++UdlWRroWzAPIjB9WJolpxHwr/9sMVGj1bC462dsULsX78v3dI+9KVWjyYIZWVCCitydVj\n2Nuq55YhlSXZLPyqf4881axjwcysEkWR6TS9Co5Kfa++xyDC7wYnCYnbj4LG84v1GjoMR8bMrHsQ\nBbCRp3cM4bRZaXrc4x2DJHSCFz3TQ7CccUF/nDu2/+bL0ua5qEKRXYZkmpldPEf9nn4Ua6WfwdC/\nIcwtTb16fvP79dy29uj4YPFnhseaxQNE6Ult+8prpc2QSe5zPsIS3352pbRvQbAmCwMzJNMs7jzl\nIaDxcJu+x2wU6mUh3j/WawBpPoKBf/GoOpl0X1+3WK9rOlZmZp/4qoYR/+5TfybtMfRzCoN9c3V+\n68H4Y7FhFs3NHNXxTN/IzKw4R889naeFFRp+3dil44/jk/7RwLGhCR+n88SxZRZ3v/geDAxNgSfN\ncO2J8G+gHMdxHMdxksRvoBzHcRzHcZLEb6Acx3Ecx3GSZEodqGBB1m2Ls7AuDa8lP0PXMlOm6f1e\ndWG8UC8dAa5Ft/bpujALDWanaJcsLdUci4cOq3fVhWKwuem6z4kyJboG1X3YeUT9oIJM3Yf5yHmq\na9d8o1u/8m1p/+h7H5d21gx9v95eXWdmYWCzeM4Tnad/umqxtK/57mPSvmJxsbRHIl1/n4F+uXie\n5qzsbNKxsKRsYkfBzOyKObrNB+u1n7JTtR/4Hv1wUrbX67k+OEv3cXA4+ZAjZpctKNVzu69L87Hy\nUvUaSYFA0jXEXCjtpwhBTN0Ye7MK4gVD6ad19OtrWEw2N12vw+5x7gX9g5cyIagTlAJX4nC7ejVV\nBdovdC/yExTEpufCHK1uuD307liYfH6mOil8/9Z+PZelWerRJDp/dLt2ten8Nbtf58zZyAra1aTz\nzRuv/Yy0N/5S87O4vd/u0JwoFgY2i+c80XnKQt7Qlib1bc+v0bmkNlevq3w4VZ+6TIvOd+IaoZdz\nVpnmTpmZ3fWJK6TNc8v5irlN7KctR/SYyuAQ52ZoH/CzKlEGWBOcpzJ4V3ubdP6iL8cCxu0Yf/Si\nu+A40eui92UWd7t4zQzCw5qsQPdE+DdQjuM4juM4SeI3UI7jOI7jOEniN1CO4ziO4zhJMrW18MYi\nWRs+2K4ZEcsrdZ25/5iuVQZUYaprj2dp9GN9Mw/1gegt0HtpGdA13i2Nul5f16HbPH+WukI7+nQN\nuDw7fo86Ax7Lw48elHZJHn0hfX05Hs9cfv6E+3xxjdbCe+tlc6X99Zs1f8QsXtuOOU90nm69fp20\n33/rVmnnM0MJ/gfryNWi5uAgChqNJSiyNjSqz6lHxhJf0wAfiXXhqoowHrEPiA+xFvh1RXD8zOI5\nZJ0D8BhStJ2JelfMgZoxbeK/gagx0NFr6Y3nqDDXaRbyY+q7tN+21KkD85oFZc/8NzPLXsqMjI5Z\nY/fJOSsVfZ+TNvF0yrmnO0GGDfOL5pbqGKST1IecqJhjMgDHKVvPZQ38yv5jOv7oVJmZTcM5/eZ9\nh6T93gs1V4412lgDcOFVr5f2zmZ1DxcUqcf19auXS3vd39wW20fWtmPOE52nZaU6j+9t0Xmc/i2d\nJmZ6zSrWfm3u0s8V1mMzi59b+j/MQKLzdBAOHj2rxk79vGWOGd+PnzNmZoWY09rgC8Xryunr6XFl\nYh84XzCjiU5VIsWS7lhRtp57elxPtuj8tbxcXdeJ8G+gHMdxHMdxkmTSG6gQQnoI4dEQwpYQwo4Q\nwj+c+PfZIYRHQgh7Qwg/CSHEI7cdx3FeQHz+chznTHEq30ANmdklURStMLOVZvbnIYRzzOyLZvbV\nKIrmmVmHmd1w5nbTcRznOeHzl+M4Z4RJHajoeJDM0wvCKSf+F5nZJWb2thP//n0z+7SZfWOi95o2\nLZ6/MR5m1NAVYjsRjDYj9gAAIABJREFUda2oXZeua7bLZmpGSRrWWNPRXoQME+ZKMTeKGRNF6fGc\nitF8Xbj9wDUr9T3gMRRmxl2a8Vz7Bn39YngTadPg0SC/6JM3rI+952OHdV2Yte2Y80Tn6RvXqKfw\n5v9UZ+opZOKsrFEHgTUH6URtPqQOg5nZhbM0i+WRnVpf750JamaNZ2GJ5vb8vEFdMjpUg6gJV4U6\ndxwrZvE6S1zz5zVQmDFxLhDHH52A8hwdO/S2EtW7qkb9xvTpOn7ScAyvXKiOndTCsxfWgTqd89f0\nadMsb9x80tKnfdc/oGOWjgnPPf0lM7MHkF1GMmLvqSeUvT0T9ffyMJcMwHnqgDNVkqPzpVnc3/nW\nW3T+eapFrxs+n/v879eukXZaysRZenSDfvUPr4ntI2vN0b1hzhOdJ7pit2zT+qF0CV8xS+uPsl95\n3W462hHb59ocnbf/Y5PWAPy7V6q72odt8FzzmDh/dQ/o3JGDbKtMeF5m8XNBR+lwn3pYdMXYLxwb\n/PxMx+vp+LGWo1nct83E48N4j3VV+rkxmkR03Sk5UCGE6SGEzWbWbGa/NbN9ZtYZRdHTM0C9mU38\n6eQ4jvMC4POX4zhnglO6gYqiaDSKopVmVmVmZ5vZolPdQAjhvSGEx0MIj7e3xRNjHcdxziSna/7q\naPf5y3GckyT1K7woijrN7A9mdq6Z5YcQnv4OsMrMjjzLa74VRdHaKIrWFhYVJ3qK4zjOGef5zl8F\nhT5/OY5zkkkdqBBCiZkNR1HUGULIMLPL7biA+Qczu9rMbjGz68zs9snea1oIkgmyqkrXfGej3tCW\nZvVw6JQkyqkoSlBfSl6DLA2ut2eP6Dpw1zHU4kFW0Jjpgmk7PIjOoXhdncYe/bcDbbpe/7olJdI+\n3K2P723Tdd9lFbr2XZimx8j8mbnF6hPlpcUdqwvnqpP0yEE9F6xtx3VnOk8/eZfmRP3Vf2+XNtfz\nU7G2XpSu77+6VtetzcxyUTfuyvVV0mZduCXl2m/0ic6bp9uoytbVdGZTpSOzaVuj+nhmZj1Duv5e\nlq37XFug5yYD/tGcYu13OnbM3EmHY1CSoc8vyI7/+KwY5/Jon+bHDEES4DYGx53LRHldU8lpnb+m\nmeWMqx+WhrwZ+mz0NVgLj46Umdm5M3XMFedMXJuOPge1Ozolx+C8cZ+fbFN/KdHcwG0c6NJxvgbH\n0IQMpFZk7TGviMfEeqW5cHVYE87MbGm2Zvn8sb5N2qxtx5wnOk9vWVYp7a3N6mAe7kUdxEjnCmY4\nnVUUr4XHa+XGddXSpj/EOnQcG4vKND+LNeHohdGfY107M7P2Qf3s4vhINF7GQ8+KczKdqG58nuZl\nTFzP1MwsFZ93B1t0fLJ+bRb8Xjp2E3EqQZoVZvb9EMJ0O/6N1U+jKLojhLDTzG4JIXzOzJ4ws++c\n8lYdx3GmBp+/HMc5I5zKr/C2mtmqBP++3477BI7jOC9KfP5yHOdM4UnkjuM4juM4STKltfBGRiNr\nHef/bKzDGqsu+dreFnUvZuVp+xjWxs3MijL1kO7do2vVR1H/bGGBrhPXcS07Wz2ZxyLdZ9bOW1mp\na9/lmfp6M7MDneo0zUP+0O42XbOtgAdRnqNr4XWdcc9K3j9fs1wOtus+n1MVd8k2tzNDRB+fgbVn\n1rZjzhOdp395/VJpf+Bn26SdxhpwONc//u3e2D5X5Or6egfWz5v6dfzsa9V+KKnWfm7r07Vw1m1i\nHbsWuEIDw/Hxyawo5skwV6WuR8fK/lbdxtJi3Qc6AyWoXbULOWlDCfZxO9ytmdjnRaU6Xo6gNt7a\nipNjI4Gi8JLl2MiYHR5Xb2wADlweHDxm5pCCRLUS03UuqEN9s65j2tc1eerytCKbag2y0Zj71Y5a\nZpfMVv+SDlai91hdObHzVApXJx9ZVP3Iw+qAg5KFLCC6PkUJ9rEV+5gPNycfLg7zinhd0nlajtp5\nu9rUEWVkIV2zz/9+T2yfL0Ge2poy7ddO9AtzEUvQz3Sq6KnS9Wnq0rklUe7iwhL9vGRdRPpr3AYd\nJ9Za5POrUYO1rk2vB3qIZvHxx+csLVI/jsedqP7js+HfQDmO4ziO4ySJ30A5juM4juMkid9AOY7j\nOI7jJMmUOlAhaD2oxWW6vrkgX9dXdzXr2iQzHzISrH+mYE02DWvbi0rVMeD6KJ0n5l6kz9D3Zz5R\nD9bze4bjmRIFyLJo7dPXzM7XfRge03Xlkmx9PVWwuXnqPDGvaAGcq/6ReE2uUuQT3bdD68pdPE/X\nkdtQu4617ZjzROfp629cJu31n71b2geaNZ8mNzfuPSwr1n06gLysVNQEZGZYrFYU6tJ1YCzkIHOp\nsUfP9cCxuF+UlQoHAOOzLEP9IubT7EtB/TWcu7Lp2i87mtQZqMjV8drQoY+bmVUXqHsxWb0+9uP4\n/KMXOAbqtDItBMsY5+aV5ei5ysF13dCh8xfzjBI5UszFYd/Phs+YAqekMlev7RZkznGbrI3H7KpE\nmTjpmDN5XHSeeF0xq2w0QhYfHJRD8F4WlGkf0A0yM8vENn7xqKbIf+oyHeNDyJJibTvmPNF5WoRc\np8/frY5TKvqsMDs+f62vVAeKGV7MQaS3xXM3WT0+9lHvsM4liRxjOnGs75iDz0OOX9Z/7IGzyX16\n6qjO+xwbe5BbZhb3AunMMQ+L/ZhMDpR/A+U4juM4jpMkfgPlOI7jOI6TJH4D5TiO4ziOkyRT6kCZ\nTZyNcrRfM2+4dpkKH+Rga9zfKEK2SnsP8kDSde2b9akCKgId7tJ92n1U85HWVKq3lQYnoRHZQ2Zm\n+9r032JOCbKs6A/dt6dD2qzZNoJ++83edmk/trtZ2jdeMju2j6zp14914Z1N2i+1hbo23g4nirXt\nmPNE5+mRT14q7au/86i0Cwri+Vq/3tci7aw03Wb7kI6Ffa04hnx1WphZwlp7OKRYdgzHr5nZoQ7d\nh2OjOhZSZqE+Fa4Xrs/3wVvox1jhNcK6dbOK1Rcwi/tshRiPLb2oDwm/oznv5DGOjMU9ipcqxx3O\nk8eaC+eJGVx0fSK4Psw/Mov7GPSHKgt0jLbCcUrH69vwOMckn1+ArKC23njG3GQZR3RV6UhtbeyS\n9rk16hvxqrlp61FpF2OOv34NAgQTvAf9oc4+Pa5Zxerj0h9ibTv2AZ2nj186X9o/2qK1qtdV6eeG\nmdlPd+hxvnvtLGnva9XPnmO4tmqQmZSJc8vMJp43MjIan784v/QN6hguhv/GOXTgmG5zBOOb/c66\niXSgVs+M10TlNUE3kS4YrzG6rhPh30A5juM4juMkid9AOY7jOI7jJInfQDmO4ziO4yTJlDpQ00KQ\n7KaybF1vz4AXs6RcPZfsVN3dRFka+fBQVtdoNlA/nJExOAGsNVWO3Iu1tfp+9GJ68P7z8+Jr3YVp\n8AwGdZ23OEO3GbJ03Th7qR4j17Lpubx1aYW0WdusJCNeCy+lVN9j9OwqaS8pU3eGWVN0opiXxdp2\nzHmi8/RfN5wt7et/vDm2z6+dXyrtPZ36nivKNJuKTh3djUrU1mPtsz7kPC2CR7GjWWvKmcX7npRm\n6rmYBidvTrFeE/kYS9zHCrhixcgQ6xyMezg1+cxy0cer8Th9ueq8k/2QMl3H6kuZYMFSxuXeDCF3\nhxk3Oai3Rl8kkWuRN6avyUvX9iE4bbHsn1E9/9kper7pg/QP6fOPdqqTV5wTH69pKRPnD43g2qYH\ns6RUM5PYb/S0blynjhPdnERRY9zm6xZrjT+6Zs2on0ZPpih74nwj5jzReXrHipnS3tKkHquZ2dWL\nK2L/Np6zyrXfmBnWjtqdzOuio8fzVIm5oh51OM3i/cB+JDw39I14rhtQT5QZiHSkmCNlFs+mijlR\n8Kgae3SbZdnxz8Nnw7+BchzHcRzHSRK/gXIcx3Ecx0kSv4FyHMdxHMdJkil1oIZHx6xx3FrzzzZr\nfbUNy3Sd+p6ndJ24erU6Jlv2t8W2wfpkj+7T59SWqpNUBuekc0jXkXux5rq9QbM4FpeoC9SMjJyM\nGfGsqp1wY9pQC29m3sS1ePYjR4pr4QPVum48v0D3kflHJVnxYXDHNq0d1Yo8LPpCXNvefKhT2qtr\nNa/jx7/dK23WtmPOE52n7751ZWyff75NvYN/vWu/tD/zOj3X9x3UPJq1VVpj697dOnYuqta8mhY4\nBwfb1aM42hXPAOP4mF+s+/RQnfZbF7yZ/Rg784u0n3LgCR5p1/GXCS9i66G4i1GVXy5tjs/H0W9Z\nabrNrtqTxzj6MsqBGhodtQMdJ/ufzmZNoV5nvTh3hfBHmvt0vJjF/aIjuO4iWCWslcjzz1p3dHdS\nILgxQy5RVhDrxjGrjF4L49Do3hC+np5NLMsqQU3UA616nRzt0348q0x9IjpTm47qdXEWa939XnOf\n6OMy54nO04qyeH4Rc8H+Z5fOwZfPVceTcHy1duv4mlOq45MZX8x4SpkeP/eMcaxALtnBFp1vuvF5\nWpSp+5iP8cnzwD7heG5PkFM2G8dJB4oZYHlp+p7J4N9AOY7jOI7jJInfQDmO4ziO4ySJ30A5juM4\njuMkid9AOY7jOI7jJMmUSuRpKdNs7jjB6wPn1crj+QieW1GiwYcMdfv0hrNi20hHcN9lc4omfJwS\nW8WISrkpkNpqcvXx8my0M7WdqHZydbbK8McgVeYiPI8SJSVMFkSm/Mfwsbct18C28tx4cFh1ju7j\nx/97h7SvmFMs7SEE+F04SyVJBo5WIKRyWbEGlLIwMEMyKYybmb1umYbV5SBEsCJHz82bl6gszZA4\nhn+W5Wk/nTNTxycFXwaimsWl3EQFh8fD4pn3H1axtApjqRQy/nvXa0HS3mGVOucVx8/9agiug5CG\n+cMJBrGO70dKyi9l0mdMt4UlJ+XgyQIkqwp1vPHHHnMTFHLuG2IgrZ5fBl9S0mUAJPufojAlXUrs\n3f3xH7RkYUxOVlyY4i8Li3N8MfBxT5sG4s4u0B97UDw2M8vP0Gv3E1/dKO27PnGFtHkd1uboueGP\nZC5ZWCjt9ZXaZmFghmQmKiSdiR9jnF+ln13sl0l/IDCJkN0CyZznsTw/PjfMwLnrxA9p+B7zSvRc\nbTyiMn0+BO6iTJ2/OP8d7lBJnUWizeJBq5P9aIHhsvzxx0S8fGY3x3Ecx3GcKcJvoBzHcRzHcZLE\nb6Acx3Ecx3GSZEodqCjSApz/eO8+efzt6yqlffPjuo786SsWSvvLv9cwRjOzxdXqpTR3a5jhbBR8\nvaBafY+mfg1c43r9XbvbpX3j2eqY1PfqGi1fb2bW0Kv7xGXczgF1Arg+396va7QMtVxfraFvJXBx\nbt2hAaYLStTVMDO7f48e56UrdQ3/wXp9vL5Tw8ke2anbuHK9FiPuwHr+gTZdj89K035jYWCGZJrF\nnadLF5VJ+64nG6X9w8cbpH3FWeoc3LldPaz3nKP9fMdu9ZF4nkpy4gFtdAQY/Ppko46f5ZXqYvzw\n3kPSvuZ8HX+vmqeu2BNNGnrJ999zRB83M2terV5DabYexyOH9FzkwyF4z7qT+5TIAXypMi0Eyxzn\nIz5Up+f/vGr1Ah84gCDEhToen6jX0FQzsyyM4aHhif/GZbFVBmGWWNzDGw9DB+lQsdCvWdyroke6\n+6iODzol9Kx4TfD95xaqR0Ons7EzHli7v1ODNH/3qT+TNsM3u+B6/cememmzoPGamCeo5+Hda/W6\nJAzJNIs7T3SYIjh325p0/CwuUY+UxzSGsTEwqudlRkCo6mjczxyB6zoNJ++BOg0fvgDhw3vadP5Z\nUKSfx3OL9VyzMPCRbv187huOj89YUW94VHSGOW8vrNAQ1Inwb6Acx3Ecx3GSxG+gHMdxHMdxksRv\noBzHcRzHcZIkMJvkTLJsxerotrseeKa9tVH9i8osdXGYvdEyoGvdgwnyHZixRAWDmSElyM3hujHX\n2/d3aTHhVRW6Fj6EtXDmrpiZzcC6cXO/Htd0rEXTEShGVgbzaLhuTIbw/HQ4CWZm+zv1OIvTkc+B\noqU8VywwynHWhGNOnab70D6kTtSKMnXbDnfGizQz5+lwl3oQV5yluU9PHFSHgF5EUy+KcRapL7K3\nVfuIvk/mjLhiODCi46EHuUzMKTvYpce5rET9too85Jbh3DN3hdfH9ra4A1Wbi5ynLD33zX1x50T2\nadx5ePOrL7IdWze9LEyoBUtWRv/y098+007HXMLiwpxb7tqrXiDztsziYzA/S/OMBjGf8LrjfMXp\nfRhzJgvQMufnaIc6J2ZmpchD45zZPaht5hPNL5vYaepAtlD7gF6HNSiOTu/LzKwJ7mtJ9sT5Qpxj\n+Z7cx04cM/OIuo/p42eV63XbPRDP12LOE/uNn12ZyAfkWJgMFhPm51JuRtzhZGbX0R7t52Nj+vhj\nR9SHu36NumQ8RvZzE96f811DZ3x8FqBgcWGWHkcPnDy6XnSozl9QuDGKorWxDZl/A+U4juM4jpM0\np3wDFUKYHkJ4IoRwx4n27BDCIyGEvSGEn4QQUid7D8dxnBcCn78cxzndJPMN1F+b2ZPj2l80s69G\nUTTPzDrM7IbTuWOO4zinEZ+/HMc5rZxSDlQIocrMNpjZ583sb8JxweUSM3vbiad838w+bWbfmOR9\nLG3cOu7Hbtoij3/pHSuk/dDhbmmvRCbOdx6si23j7Llak+hAizokK5GRxHpmXLtu6tP19x1N+n55\nqfqH68ajus9V+fE/bHnXuvWovueScl3n7R6k96Dryo09us9vPEvzZrg0fn+dZjjNyo9nxTyErJ9K\n1K5j9lRDt66nEx7Tvlbt16KsGXgceVzTtNfuOxh3d1jbjjlPrNm2qlbP/a2bdTzdghyyD104W9pf\n+t0eaV+6RPu9fzjuv9UW0l/Tk/NEvXpVF87VbJc/HlFva9GQ9ntNnl4jzF1p6NF+39qg2zMz25Gh\nfV+DMbypTsfGyirNTclLO/n8ZL2MM8Hpmr9SZ0yT2nQf+K+t8vg336TzF+vaLS7SuWcvss3MzGZm\nqaPWCAekAPUZmYNDN5Gwfhrzi9qRqZSWIMeOnlYP/KEy1Nakt8Vt0qGaW6ZjOLMj7miOh/6S2fG6\nheNhphJdHmZV9WGfy+Cz0RdivdJjyOc6FdeY54Y5T/Rt6dfSf9zdihqC+dqvP9is8+Nfom4mfTmz\neH08umQ/2abv+ealmh+Yjn7qgIfF81SZN3Ft2aKs+Ocrr7sOPN6Cz/Q5qEmZTHbdqX4D9TUz+1sz\ne7pHi8ysM4qip0ddvZnNTPRCx3GcFxifvxzHOe1MegMVQniNmTVHUbRxsuc+y+vfG0J4PITweHtb\ny+QvcBzHOU2czvmroy2eHu04zp8up7KEd76ZXRlCeLWZpZtZrpn9s5nlhxBmnPgrrsrMjiR6cRRF\n3zKzb5mZLV+55oX/Pt9xnD8lTtv8tXTFap+/HMd5hklvoKIo+piZfczMLITwCjP7X1EUvT2EcKuZ\nXW1mt5jZdWZ2+6lscHy8xpffsVK3ZTo/zSnSdecs5OpcvkTrfpmZPdWszseGJVqfqhAOQTnW69P7\ndI22H7k92ahdVpSh77emQj2Hj926LbaPH7lKa/otKNV9aOhWJ+CeXfrN3bXrdbVhFnJZ6HFlTNd+\nm1uo68ojY/G17pWV6mLU5Gqbfk8P1p0Xor5eNmp8lVTruaUrU4u1djpXa6s0S8bMrAiZNqxtR3eD\nztM1KzWjhOeedQ4/evkCaW9uUv9tXamOhUTvueWIvuaNS1HLrlE9BnoOlch1Yo7KQqzvz0A/8v2O\nv+fE9dMKUPvuGHJUXkyhT6dz/hqLIunf7719tTzegMykrDT2k15nS1G7zMzsx3BI3r++RtrMcMsZ\nwzbwON0e+kb0bsoxl5z7tz+P7eO9//tKaTOfaGODOpbfhav6b9eoK8YsqkPwVpnLQw+nuSvuX2Zh\nni6Fw8R+Odiu25wJ9yZW5zJ34iy+GtR4a0e2FY/ZLJ6JxNp2nCN57bLG24oKdTzv2K21QD9x6Txp\n74C/u6wyPn8xq+rXe1DzFPUeHz6itfHWlaujnI+MpkNwNueW6jzP85CdHp9tWJuRTlRNoZ6bHhwT\n/biJeD45UB+x40LmXjvuFHznebyX4zjOVOLzl+M4z4tT+hXe00RRdI+Z3XPiv/eb2dmnf5ccx3FO\nPz5/OY5zOvEkcsdxHMdxnCRJ6huo58vI2Ji1j8t9uG17szy+Cl7LF36gP5z567eukvZnP3dLbBvv\n+/Abpf3LHfrLGdZxujpV10sb+tRj2I31+PufVB9pGTJLtjZq/bV3Xz4nto+bjmj2TgOyV1YgV+e6\nc6qk/cABXavu6lcH4E0rNQ8pLUN9gMfq1aupTpBVVdep77m3Vfdxe73mMFWhTtzPG3Qb583TDJO2\nPtbP0nVnehXMobp3t66tm5kVwW+7c7ueq+ocXftmzhP9pOvW1kr79m3qGf9gk7bTsM8P71MXxMxs\nZmFW7N/G87v9mlpSlKmX6C8e123Ox3p+DnKAbsc1loP6Vodbdbyamc2Gd0AHhZ5VCrKCSsbVohpO\n4Ne9VBkZi6xt3LVGHyMNNSU/+etd0n7Xer2O3/KNTbFt3PS+c6TNul30OZhHNA1t1rbrR25UToRc\nKJzr333mNbF95DbpjKybqZ7LhndrFlBjl+bwNKE9s0Dn6JwM1q3T7Rck8ImYy8R+3II8tbPKkNHV\nonP0ojKdkyerQcg6dfQvW7v1mM3iGUj01Ypz9DiZ80Tnicd8YbU6oXSeCtJ1LOxqiueUVeXrfPOK\nGnWMG1CDkM5TXbd+nhZm6z7nwBtsQ24dPTGOb7N4LlhDt36ms7Zn7FyOTI0D5TiO4ziO8yeJ30A5\njuM4juMkid9AOY7jOI7jJEk4lRo9p4uVq9dEv7vvkWfaW+p1Hbo4U9cmubbO9c5erNebme1Bfam8\nNF3XLcvU9fXCTF1XZm/0DOg69GFkAc3LV1+kGXV2EtXVKUhDPasRPY58uDxt/fqeOfC2OgbVVyrF\nGi99ImZ50N0xM+s9ps9hzaGDnerO0B/iunIV8ooy4YvwGHJxjFyXzpgRr49VBr9tZ6Ou8c8r1nO1\nv02PgTlP9ImuWqb5W5sP6vjd363exOzceFbVUx26T0dRx/CianUG6NXUdes+F6bruWYdsq2Nuo/s\nx9QEDkEm+jZ1mrbpwDDfaH7JyeN+wxUX2LYtm15M0VDPmaUrVkc/+80Dz7SHkf1Dh4V1wo4iJ6oC\neUZmZnfvU2eN9fPom9FzYa4T84k430PjijlSXUM6Ps3MFsMX4nvQQWmB71NRoBlLdH24j8w3Ksia\n+BjN4q4Ms6OeOqrXKt+DWXpVyIXKx3xIp6k0T6/Lhg51g+aUxl3IfnyedcATTYNHRe/qvsPqhdJ5\noh9HT2wvnKqlFfGcMnpTO/CaV8KJ4jUwxNqL8HcL8HlM/7J1QPt5Vp5+rpjFxwtdReYFchu8z1he\nnbMxiqK1sQ2ZfwPlOI7jOI6TNH4D5TiO4ziOkyR+A+U4juM4jpMkU5oDNTam67YP1amfsWG+1gG7\naZvm9Lxqvq7pfvWe/bFtvP3sSmn/apeuCy+u0LXnV83TbbYgd2IU6/HbkPNEB4o5UukJXJ2hUV27\nfqRe15VrClC36ZiuGzMLphBZQdznUrhlfzikfVKaEx8GLb26LlySrc8ZHNZtUKUZHInQ1n3uHNB2\nDmpX8f360ActfXE345yZrP2kGWBMtPnS7/ZIm7XtmPNUk6NjZ2Wtbu/+B7Rfd6Iuo1ncDymCs3L9\ndx6V9qffvFTaDx3SsXLlwhJpc71/S6O6Hh39el5HRuMOZEaqdv4C1DXc2qDXQFW+jq/xLuMIBZmX\nEXQ06bVsPqTzWyYybu5EbTIzs4tr9XzWdeoYykQ90LI8eqN6ndD9YQ04OirNXerqpE2Pz18F8H8O\nteo+TuZZdfap98JssiH0a1qKXjQ8hkQOVDodS8wXuciW4vO7BybOnqK3lRmbv/T5I/AE23rj9fvo\nig2M6nHy3P9gs9ZNnKy23Wxk9dGhqszR65z7Yxb3a6uRC7Xhi7+X9i8/com0ea4q83WbGfC86Bny\nsy3R9NI1pH1Lt/pIp35G07viuZoI/wbKcRzHcRwnSfwGynEcx3EcJ0n8BspxHOf/tXemwXFd55l+\nD/YdDaCxEiDBBSREUhJBkVqslVoyXmLJjmXJmbisyHJUM3E5duIqWyrPaDKTH3EqiRO7xmOPK4kT\nW/FEtjSKNFIi26KXyJEtixTFTVzAHQSJfd9B4swPtKR+39ME0MUm0JS+p0pFHKD79rnn3nv6qs/T\n72cYhpEki+pAAZwPtLKc1+d3d7MzoOvxmp9UI+unQJhrUyaOyZ/873+n9p1f/hC1RzQHRfJABqVm\nW+co97FQ1tJLc8I6Td3j8hzJ46jI5+dMn5e1aFlvnxSPRTOSNAcqJ4vX5xMt+faKK6O1nJTuUX58\nfSnvg7pg3TJuHZKHVJLHj2+O8lr7ib5wfd5j7vwPzeS6Y0M1tV/vZGdA87E050mdp8/ctJra93/7\n1aCP/eLYFYr/8fkPNVM7J4P7UCh+0qicr+qH9IzwuDZX8TWz81RY7yo7i4+delt6vmodw/hxU3fk\ncmcm7pxaIefkPnEZO8akLlgFZ3xdGQ1zdtSlqS7iOfLaz32f2ju+dj+11R/qS+DaxKP5ReojFeWF\nkom6M+oTaVaV9kFfQ1EvS9HzUXN/gNBPKzjP4+rc3F6V9lHP4k55b9L3DaVOsq/GpsJ6a7pfWY7H\nUfPXfv+65dSer7ad5jyp86RjsqMjrOXZ2s37rb7kU394K7W1JmB2Jr+Gnq8TMi6ax7W+ijPINNMQ\nCOcczXWKyLFV50mz1ObCPoEyDMMwDMNIEruBMgzDMAzDSBK7gTIMwzAMw0iSRXWgzs14yuM40sN5\nDKsqeL2/Smqb6TpzXk6YUbJHcpp2HGVP5d57NlFbM0t0nfn8jNRIkto90/L3QamrU1UQ1rs60MX7\nrU6JZl2o79NqfUJGAAAgAElEQVQvGSTVJVLbR8ZpZpS3d1K2d8uq0MXIzuDHHE6QaRRPhdSnypR1\naM3PGpe8mnHJeVJ/aX8XP/+sOAgAEM3nvI/KYu6T5qiMyfr7Vllf/+VRdgC0tp3mPKnz9MSDW4M+\nfvw7O6ndEOVsFlWGtMbgzuP91F4mrpnWhpqW9f1pGdcz/eFxrSjmbeqx7JMcnzapKfj+prfrYZ2b\nWXimSrozdX4GpwcvfB2oJ9hUUUztyXPzuxbtfTw37O0ZpPbffek/UFu9Gc0z0vpnmsOjbo86KVo3\nDADaermPWvdNM5C0PuiwzJGVxfx87/n56rmos6LvEwAwKk5Tl7hemk9WI9tQd+dIJ/uP89WD1Hy1\n08M8ZuoCAWFml25D50S9tq+s4/nrYOfcte0050mdp+uXce4iAFTk8zYbpMap+rZhLh17zhVSy7NR\nsqq01qOeW91j4ftAdeHcx7JnmLf5qzM8p15fVxZs80LYJ1CGYRiGYRhJYjdQhmEYhmEYSWI3UIZh\nGIZhGEliN1CGYRiGYRhJsqgSuXMsz6l0OSIhWhoaqCGZk9OhoFojAux1cUIrEBbeVelNRWN9hRdf\nOkrtD6zn7WsR3rEpDjcDgDMDLL7VRUIJMp6GCO+TCoi5Mi4qIpfksKxaK9J5QYKCx30iqteJrNwx\nxCJxnWwzS/o4PMkjqUGbeqxP9rPgqLJ010hYTFgFQxVsx0XIbixngVGF7WXlLDQe7udjqdvXkEwV\nxgHg8U9cQ+0rH/1XahfczmGca6N8bmxuZMFRvm+QMKAvngMdLEHXlIVhtK/JFy+0mLAWxV1Xx3Jq\nfJDrOylIM9M5FGe/fS3pOT4kBbIjUnRX5xoNb0z0nG3FXOx8aFyK2Iogq6GSej78tx8epPZ/vZML\naI/Kddo+yPIzEIYLF0uQZqGcH3UlfA5rYKMK2fr3YgnW1NhMLUALAO193MeovC90ikBdLl+C0T70\nTfB8t66SvyAQFRFex11l/ESXhQY+npOi8xoOqtK5yvb1UuhXgza1MLCGZKowDgBN5bzff/TPe6n9\nB7etpPbaKIvt1zawmH5IRPched/RL1Qd7BKJXb40AwBP7OMiyw+01FM7V75oodK4zm9zYZ9AGYZh\nGIZhJIndQBmGYRiGYSSJ3UAZhmEYhmEkyaI6UBnO0fpixzCvK18RnTvASsPKygrDIDotQjs0wW1d\nL9fCmJOy7qyBj1uvaaC2+kdXVPKa7FN7OoM+bmrgdWH1WCbFxamQwL0BcS3UxdAgzayiuT2UgcnQ\nJ9q6nEMj2wb4WK2t4v3UPqmPVF3E+6DHqUhcjqnzYUBaPE3R0BvT0LZiKcw6PM37OXVOQt7aQ18t\nnrNS8FiPixYG1pBMIHSe9v7p+6j9xK5T1FYHb0A8h6iMqxZArilhzyFbjsvJvtBx+eDmWmoXy7GJ\niPOSJ68Z73K8gxQoZGQ48n3aB3jsakvZFVN3Z1D8DnWigPC6mW/8+kZ5m/rwUQmtfPC6eszFsnLe\nh8d+eDh4zOdubKS29lk9LQ33VJdHQy3HxQ2LyHWm+9Q1HXp/jTIPa2hktVwXvVLwWAsil+ZyHzSg\nNJiDZR/y5RqqLQvnrwE5lvoaZ4d5TtSiyy+08nvNbSvYz90vxYQbxJHSwsAakgmEztNXPnQltWfk\nWGpxYB2XgSke92VyDZU43scCOZc0VBUAPrGJz3F1yzLFE1TnSd3WubBPoAzDMAzDMJLEbqAMwzAM\nwzCSxG6gDMMwDMMwkmRRHSjA0xrpqR7JpNnI7sXeLi7gOF3K652RvLD7/WO8xjopa6SFkolUNk9W\ni+ZCtdfzmu2Gas7AOdHHhVU/dyPnYgDAoDhHp0d4HJYXszvTO8Hr97reXiRr11dWRaitjkGz+AFR\nKegIAIcHeL38fasrqX10kI/NSDavdQ9NSOZSmbg4si5dnc9OQPZy3kctyvxyGxelTIRmHjVXsNe1\n6zTvw0c2cubOi8e4yOQtDeXU/uTf/pran/9QM7UT+Sua86TO0/0ty6n9Ums3tdsjfP7duIz7VCIe\n1pU1fC7puTA8GfojDVJYVc+PYfEaWuR8i/ewXGDlXL7MzHjKbvqnvR3090du42N7ROYvJS9B/lrP\nGF/r+fKY7Ay+burEpdHcLc1o0gyltbWc66NFdx+7synoo+b3DYjbpU7JgBSf7pWC7MU5/Hjt01nJ\nzdOcqRmVSBE6T+tkm1ocWP3JU6M8d6gDNS1FmYvz+H0kWhLOqfGc6A6LUqt784s2zmNrjLAf9MRe\nzju6e101tc8M8bhtEyfqA3/2E2o/9Ye3UjuRo6c5T+o8qbelTqb6cZtqeO7Q15zxfP6Pif/WPxb6\nu+qGaW7imJwver4d7Zz7uo3HPoEyDMMwDMNIkgV9AuWcOwFgGMB5AOe891ucc+UAngDQCOAEgPu8\n9/0X2oZhGMZSYPOXYRiXgmQ+gdrmvd/kvd8Saz8CYLv3vgnA9ljbMAwjHbH5yzCMlHIxDtQ9AG6L\n/fwPAH4G4ItzPcHB0XrkPVexV6M1aupKeN25rpjXgIvywrXK9VFez3z1zCC1V5eyB6OZIh2StaF1\nn9Rr6ZP8kDHJJCnN5bVxAPhFG/+PrmZHqX/0J999ndp/+iDXUxuUfegTx0AVgc5RyUQpCDNJmss4\nq0o9rVJxybSeXnk+v2h+Jv+9bZgzdNTt0FpUGeLSDCaoI6Zr31fVsf9zYpD34ebV7K/t6uBxr5C6\niXp+/vH9G6mdI/ugtfWAsLadppio83RzE18jP9jHWS/tUd6ngUk+9tPiALb28rgX5ob/D6WelPpu\nU+J/vHi8h9q/ufZtl8wH1k3akPT8leEc5fl8+voV9Hf1jaqkPpq6O+qDAEBNKV936v/US06TOkuj\n4rSp/6F1505LDpg6LXpNAcDLJ9nN2VLPHt6Rbr6O7v4vz1J71//82Jx97hzkfe4ZmdsLqyoNfaOm\nGp7nO2Sb6r7qvK65TYpmemkWlro8ehUMJcjeW1PJfb5J6sY9fZCv/fvFGf5lOx+XrTV8XAokF+/5\nL97Of5d9Vi8MCGvbac6TOk+TMlcck7kkOsXHrmecj/XmOt6H1j5+fmNpmLWn73fHe9hLLs3j9y6d\nc6MFc/tr8Sz0EygP4EfOuZ3OuYdjv6v23p+N/dwBoDrxUw3DMJYUm78Mw0g5C/0E6ibvfbtzrgrA\nj51zVNLbe++dcwn/VzM2YT0MAMvqGxI9xDAM41KSkvmrdpnNX4ZhvM2CPoHy3rfH/u0C8DSAawF0\nOudqASD2b9cFnvst7/0W7/2W8orKRA8xDMO4ZKRq/iorjyZ6iGEY71Lm/QTKOVcIIMN7Pxz7+TcA\n/A8AzwJ4AMCXY/8+s5AXjP/fvB+8xjkq7hpeR/7X/bymW5jN3f331r5g+z0jvLb8y8PsZ4zKmu2H\nm/mT+3HxVtQX2nWC84fuXMnr1HskQ2LsXOjqdAyxp6JLzeXiUnzq7g3Ufu0Mr+mqk6LlgTZWshd2\n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\n",
            "text/plain": [
              "<Figure size 720x360 with 2 Axes>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0q8k-Mg0Iqy8",
        "colab_type": "text"
      },
      "source": [
        "# NON SIMPLE FEATURES"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IqnShVUBHqUs",
        "colab_type": "text"
      },
      "source": [
        "### mod_adam\n",
        "Modified adam optimizer for convex problems. We find this simple modification to the adam optimizer removed the need to guess/adjust the learning rate, and required far less steps for convergence."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "SWap4itMron7",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import tensorflow as tf\n",
        "from tensorflow.python.keras.optimizer_v2 import optimizer_v2\n",
        "class mod_adam(optimizer_v2.OptimizerV2):\n",
        "  \n",
        "  def __init__(self, learning_rate=0.5, b1=0.9, b2=0.999, name='mod_adam', **kwargs):\n",
        "    super(mod_adam, self).__init__(name, **kwargs)\n",
        "    self.rt, self.b1, self.b2 = learning_rate, b1, b2\n",
        "\n",
        "  def _create_slots(self, var_list):\n",
        "    for var in var_list: self.add_slot(var, 'm')\n",
        "    for var in var_list: self.add_slot(var, 'v')\n",
        "\n",
        "  def _resource_apply_dense(self, grad, var):\n",
        "    m = self.get_slot(var, 'm')\n",
        "    v = self.get_slot(var, 'v')\n",
        "    m_tmp = self.b1 * m + (1 - self.b1) * grad\n",
        "    v_tmp = self.b2 * v + (1 - self.b2) * tf.reduce_sum(tf.square(grad))\n",
        "    l_tmp = self.rt / (tf.sqrt(v_tmp) + 1e-8)\n",
        "    updates = [m.assign(m_tmp), v.assign(v_tmp), var.assign_add(-l_tmp * m_tmp)]\n",
        "    return tf.group(updates)\n",
        "\n",
        "  def get_config(self):\n",
        "    return super(mod_adam, self).get_config()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "outputId": "468b0bac-ed8b-4700-f273-65e9dbc33f38",
        "id": "ILsGZjh_TlYx",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 68
        }
      },
      "source": [
        "%%time\n",
        "V, W = GREMLIN_simple(msa, msa_weights, opt=mod_adam, opt_rate=0.5)"
      ],
      "execution_count": 18,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "loss: 26871.985652923588\n",
            "CPU times: user 2.3 s, sys: 171 ms, total: 2.48 s\n",
            "Wall time: 1.96 s\n"
          ],
          "name": "stdout"
        }
      ]
    }
  ]
}